package com.yun.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yun.reggie.common.R;
import com.yun.reggie.dto.DishDto;
import com.yun.reggie.entity.Category;
import com.yun.reggie.entity.Dish;
import com.yun.reggie.entity.DishFlavor;
import com.yun.reggie.service.CategoryService;
import com.yun.reggie.service.DishFlavorService;
import com.yun.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author xiao
 */
@RestController
@Slf4j
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping
    public R<String> add(@RequestBody DishDto dishDto){
        //log.info(dishDto.toString());
        dishService.addWithFlavors(dishDto);
        //清理菜品的所有缓存
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
        return R.success("保存成功！");
    }

    @GetMapping("/page")
    public R<Page<DishDto>> page(int page, int pageSize, String name){
        Page<Dish> pageInfo = new Page<>(page,pageSize);
        Page<DishDto> dishDtoPage = new Page<>(page,pageSize);
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasLength(name),Dish::getName,name).orderByDesc(Dish::getUpdateTime);
        dishService.page(pageInfo,wrapper);
        //把pageInfo中的除records的数据复制过去，因为records保存的是Dish类型数据
        //对象拷贝,忽略records属性
        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
        //需要把List<Dish>改造成List<DishDto>
        List<Dish> dishList = pageInfo.getRecords();
        List<DishDto> dishDtoList = new ArrayList<>();
        //遍历List<Dish>中的Dish，把数据转移到<DishDto>
        for (Dish dish:dishList) {
            Long categoryId = dish.getCategoryId();
            Category category = categoryService.getById(categoryId);
            String categoryName = category.getName();
            DishDto dishDto = new DishDto();
            dishDto.setCategoryName(categoryName);
            //其余属性使用对象拷贝
            BeanUtils.copyProperties(dish,dishDto);
            dishDtoList.add(dishDto);
        }
        dishDtoPage.setRecords(dishDtoList);
        return R.success(dishDtoPage);
    }

    /**
     * 根据菜品id，查询菜品信息和口味信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<DishDto> queryById(@PathVariable("id") Long id){
        //获取菜品的普通属性
        Dish dish = dishService.getById(id);
        //获取菜品的口味
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,id);
        List<DishFlavor> dishFlavorList = dishFlavorService.list(wrapper);
        //把以上属性封装到数据传输对象DishDto中
        DishDto dishDto = new DishDto();
        BeanUtils.copyProperties(dish,dishDto);
        dishDto.setFlavors(dishFlavorList);
        return R.success(dishDto);
    }

    /**
     * 修改菜品，需要修改菜品表和口味表
     * @param dishDto
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody DishDto dishDto){
        dishService.updateWithFlavors(dishDto);
        //精确清理菜品缓存
        String key = "dish_"+dishDto.getCategoryId()+"_1";
        redisTemplate.delete(key);
        return R.success("保存成功！");
    }

    /**
     * 实现了批量操作
     * 删除菜品，需要删除菜品表和口味表中的数据
     * 删除菜品的前提是没有套餐关联
     * @param ids
     * @return
     */
    @DeleteMapping
    public R<String> delete(Long[] ids){
        for (Long id:ids) {
            dishService.deleteById(id);
        }
        return R.success("删除成功！");
    }

    /**
     * 实现了批量操作
     * 停售，起售菜品.虽然也是修改菜品，但是只是修改状态值，不涉及口味表
     * @param status 状态值0-停售，1起售
     * @param ids   操作的菜品id
     * @return
     */
    @PostMapping("/status/{status}")
    public R<String> changeSalesStatus(@PathVariable("status") int status,@RequestParam List<Long> ids){
        dishService.updateSalesStatus(status,ids);
        return R.success("修改状态成功！");
    }

    /**
     * 此方法改造为下面的方法
     * 根据菜品分类id或菜品名称查询菜品
     * 注意：停售的菜品不需要查询出来
     * @param dish
     * @return
     */
    @GetMapping("/list1")
    public R<List<Dish>> list1(Dish dish){
        //log.info("分类id：{}，菜品名：{}",categoryId,name);
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //使用分类id查,id不为空才查
        wrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
        //使用菜品名查，菜品名不为空才查
        wrapper.like(StringUtils.hasLength(dish.getName()),Dish::getName,dish.getName());
        //查询状态为1的菜品（起售状态）
        wrapper.eq(Dish::getStatus,1);
        //添加排序条件
        wrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(wrapper);
        return R.success(list);
    }

    /**
     * 根据菜品分类id或菜品名称查询菜品
     * log.info("分类id：{}，菜品名：{}",categoryId,name);
     * 注意：停售的菜品不需要查询出来
     * @param dish
     * @return 返回菜品信息和口味信息(dishDto)
     */
    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish){
        List<DishDto> dishDtoList = null;
        //构造key,dish_1397844263642378242_1
        String key = "dish_"+dish.getCategoryId()+"_"+dish.getStatus();

        //先从redis中获取缓存数据
        dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);
        //如果存在，直接返回，无需查询数据库
        if (dishDtoList != null){
            return R.success(dishDtoList);
        }
        //不存在，查询数据库，将查询的菜品信息缓存入redis，并返回
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //使用分类id查,id不为空才查
        wrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
        //使用菜品名查，菜品名不为空才查
        wrapper.like(StringUtils.hasLength(dish.getName()),Dish::getName,dish.getName());
        //查询状态为1的菜品（起售状态）
        wrapper.eq(Dish::getStatus,1);
        //添加排序条件
        wrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> dishList = dishService.list(wrapper);
        dishDtoList = new ArrayList<>();

        //循环遍历每个菜品，查询菜品对应的口味
        for (Dish dish1:dishList) {
            //根据菜品id查口味，封装到DishDto中
            LambdaQueryWrapper<DishFlavor> dishFlavorWrapper = new LambdaQueryWrapper<>();
            dishFlavorWrapper.eq(DishFlavor::getDishId,dish1.getId());
            List<DishFlavor> dishFlavorList = dishFlavorService.list(dishFlavorWrapper);
            //将以上数据移植到DishDto中
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish1,dishDto);
            dishDto.setFlavors(dishFlavorList);
            //添加到集合中
            dishDtoList.add(dishDto);
        }

        //将数据库查询的数据，存入缓存，设置60min过期
        redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);
        return R.success(dishDtoList);
    }
}
